﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using SAM.Framework.ExportData;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using System.Reflection;

namespace SAM.Framework.ExportOffice
{
    public class DefaultExportExcel : IExportExcel
    {
        private HSSFWorkbook workbook;

        private ISheet sheet;

        public DefaultExportExcel()
        {
            workbook = new HSSFWorkbook(); 
        }

        public void Dispose()
        {
            this.workbook.Close();
            this.sheet = null;
            this.workbook = null;
        }

        public MemoryStream Generate<T>(IList<T> list, ExportOption<T,PropertyInfo> option)
        {
            this.sheet = this.workbook.CreateSheet(option.SheetName);
            this.RenderHeader(option.Columns);
            this.RenderBodyOfObject<T>(list, option.Columns, option.formatter);
            return this.WriterMemoryStream();
        }

        public MemoryStream GenerateOfDataTable(DataTable data, ExportOption<DataRow, DataColumn> option)
        {
            this.sheet = this.workbook.CreateSheet(option.SheetName);
            this.RenderHeader(option.Columns);
            this.RenderBodyOfDataTable(data, option.Columns, option.formatter);
            return this.WriterMemoryStream();
        }

        private MemoryStream WriterMemoryStream()
        {
            MemoryStream memory = new MemoryStream();
            this.workbook.Write(memory);
            memory.Position = 0;
            return memory;
        }

        /// <summary>
        /// 绘制表头
        /// </summary>
        /// <param name="cols"></param>
        private void RenderHeader(IList<ColumnInfo> columns)
        {
            var row = sheet.CreateRow(0);
            for(var index = 0; index < columns.Count;++index)
            {
                row.CreateCell(index, CellType.String).SetCellValue(columns[index].Text);
            }
        }

        private void RenderBodyOfDataTable(DataTable data, IList<ColumnInfo> columns, Func<DataColumn, DataRow, object> formatter = null)
        {
            int irowNum = 1; //有header一行
            foreach(DataRow row in data.Rows)
            {
                var dataRow = sheet.CreateRow(irowNum++);
                for (int irow = 0; irow < columns.Count; ++irow)
                {
                    string key = columns[irow].Key;
                    var columnInfo = data.Columns[key];
                    object val;
                    if (columnInfo == null)
                    {
                        val = string.Empty;
                    }
                    else
                    {
                        val = row[key];
                        if (formatter != null)
                        {
                            val = formatter(columnInfo, row);
                        }
                    }
                    this.RenderRow(val, dataRow, irow);
                }
            }
        }

        private void RenderBodyOfObject<T>(IList<T> list, IList<ColumnInfo> columns, Func<PropertyInfo, T, object> formatter=null)
        {
            PropertyInfo[] properties = typeof(T).GetProperties(); //获取T的所有属性

            //获取列
            Func<string,PropertyInfo> funcFindColunm = (key) =>
            {
                PropertyInfo property = null;
                foreach (var item in properties)
                {
                    if (item.Name.ToLower().Equals(key.ToLower()))
                    {
                        property = item;
                        break;
                    }
                }
                return property;
            };

            Int32 rowNum = 1;
            foreach (T item in list)
            {
                var dataRow = sheet.CreateRow(rowNum++); 
                for (int irow = 0; irow < columns.Count; ++irow)
                {
                    var colInfo = columns[irow];
                    string colName = colInfo.Key;
                    var property = funcFindColunm(colName);
                    object val;
                    if (property != null)
                    {
                        val = property.GetValue(item, null);
                        if (formatter != null)
                        {
                            val = formatter(property, item);
                        }
                    }
                    else
                    {
                        val = null;
                    }
                    this.RenderRow(val, dataRow, irow);
                }
            }
        }

        /// <summary>
        /// 写一个单元格
        /// </summary>
        /// <param name="val"></param>
        /// <param name="dataRow"></param>
        /// <param name="irow"></param>
        private void RenderRow(object val, IRow dataRow, int irow)
        {
            if (val==null)
            {
                dataRow.CreateCell(irow).SetCellValue(string.Empty);
            }
            else
            {
                if (val is DateTime)
                {
                    dataRow.CreateCell(irow).SetCellValue((Convert.ToDateTime(val)).ToString("yyyy-MM-dd HH:mm:ss"));
                }
                else if (val is int)
                {
                    dataRow.CreateCell(irow, CellType.Numeric).SetCellValue((int)val);
                }
                else if (val is Enum) //枚举类型，必须格式化处理
                {
                    dataRow.CreateCell(irow).SetCellValue(val.ToString());
                }
                else
                {
                    dataRow.CreateCell(irow).SetCellValue(val.ToString());
                }
            }
        }

    }
}
